local skynet = require "skynet"
local time_manager = require "common.time_manager"

local gSyncTick = 33
local gMaxSpeedUpFrame = 2

local RaceSyncManager = {}

function RaceSyncManager:new(room)
    local o = {
        room = room,
        syncDatas = {},
        frames = {},
        curFrameId = 0,
        tempFrames = {},
        started_ = false,
        proc_ = nil,
        startTime_ = 0,
    }
    setmetatable(o,self)
    self.__index = self
    return o
end

function RaceSyncManager:addSyncData(d)
    table.insert(self.syncDatas,d)
end

function RaceSyncManager:getSyncDataByIndex(index)
    if (index < 1) or (index > #self.syncDatas) then
        return nil
    end
    return self.syncDatas[index]
end

function RaceSyncManager:getRoom()
    return self.room
end

function RaceSyncManager:getFrames()
    return self.frames
end

function RaceSyncManager:getCurFrameId()
    return self.curFrameId
end

function RaceSyncManager:canInputFrame(frameId,open_id,index)
    --if (frameId <= self:getCurFrameId()) or (frameId - self:getCurFrameId() > gMaxSpeedUpFrame) then
    --    return false
    --end
    if (index < 1) or (index > #self.syncDatas) then
        return false
    end
    return true
end

function RaceSyncManager:addInputFrame(frameId,open_id,index,data)
    if not self:canInputFrame(frameId,open_id,index) then
        return false
    end
    frameId = self:getCurFrameId() + 1
    local f = self.tempFrames[frameId]
    if not f then
        self.tempFrames[frameId] = {}
        f = self.tempFrames[frameId]
    end
    f[index] = {
        index = index,
        data = data,
    }
    return true
end

function RaceSyncManager:_process()

    local lastTime = time_manager.getmillisecond() + gSyncTick
    local curTime = 0

    while self.started_ do

        curTime = time_manager.getmillisecond()
        if curTime - lastTime >= gSyncTick then
            lastTime = curTime
            self:_update()
        end

        skynet.sleep(0)

    end

end

function RaceSyncManager:_update()

    self.curFrameId = self.curFrameId + 1

    local curFrames = self.tempFrames[self.curFrameId] or {}
    self.tempFrames[self.curFrameId] = nil

    table.insert(self.frames,curFrames)

    for _,d in ipairs(self.syncDatas) do
        d:onNotifySync(self.curFrameId,curFrames)
    end

end

function RaceSyncManager:isStarted()
    return self.started_
end

function RaceSyncManager:getStartTime()
    return self.startTime_
end

function RaceSyncManager:start()

    if self.proc_ then
        return false
    end

    self.started_ = true

    self.startTime_ = time_manager.getmillisecond()

    self.proc_ = skynet.fork(function()
        self:_process()
    end)

    return true

end

function RaceSyncManager:stop()

    if self.proc_ then

        self.started_ = false

        skynet.killthread(self.proc_)

        self.proc_ = nil

        return true

    end

    return false

end


return RaceSyncManager